package com.leyou.order.service;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.leyou.common.auth.pojo.UserHolder;
import com.leyou.common.auth.pojo.UserInfo;
import com.leyou.common.constants.LyConstants;
import com.leyou.common.exception.pojo.LyException;
import com.leyou.common.utils.BeanHelper;
import com.leyou.common.utils.IdWorker;
import com.leyou.item.client.ItemClient;
import com.leyou.item.pojo.Sku;
import com.leyou.order.mapper.OrderDetailMapper;
import com.leyou.order.mapper.OrderLogisticsMapper;
import com.leyou.order.mapper.OrderMapper;
import com.leyou.order.utils.PayHelper;
import com.leyou.user.UserClient;
import entity.AddressDTO;
import io.seata.spring.annotation.GlobalTransactional;
import leyou.order.dto.CartDTO;
import leyou.order.dto.OrderDTO;
import leyou.order.dto.OrderVO;
import leyou.order.pojo.Order;
import leyou.order.pojo.OrderDetail;
import leyou.order.pojo.OrderLogistics;
import leyou.order.pojo.OrderStatusEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Service
@Slf4j
@Transactional
public class OrderService {
    @Autowired(required = false)
    private OrderDetailMapper orderDetailMapper;
    @Autowired(required = false)
    private OrderLogisticsMapper orderLogisticsMapper;
    @Autowired(required = false)
    private OrderMapper orderMapper;
    @Autowired
    private ItemClient itemClient;
    @Autowired
    private IdWorker idWorker;
    @Autowired
    UserClient userClient;
    @Autowired
    private StringRedisTemplate redisTemplate;
    @Autowired
    private PayHelper payHelper;
    @GlobalTransactional
    public Long buildService(OrderDTO orderDTO) {

        //1.保存订单表数据
        UserInfo userInfo = UserHolder.getUser();
        Order order = new Order();
        order.setOrderId(idWorker.nextId());  //雪花算法生成Id
        //计算订单总金额
        //1)取出所有CartDTO 
        List<CartDTO> cartDTOList = orderDTO.getCarts();
        List<Long> skuIds = cartDTOList.stream().map(CartDTO::getSkuId).collect(Collectors.toList());
        //3）根据SkuId集合查询Sku对象集合
        List<Sku> skuList = itemClient.findByIds(skuIds);
        //4）设计一个Map集合，存储所有skuId和num
        Map<Long,Integer> skuMap = cartDTOList.stream().collect(Collectors.toMap( CartDTO::getSkuId , CartDTO::getNum ));
        //5）计算商品总价
        long totalFee = skuList.stream().mapToLong(sku -> sku.getPrice() * skuMap.get(sku.getId())).sum();
        //2.保存订单明细表数据
        order.setTotalFee(totalFee);
        order.setActualFee(1L);
        order.setPromotionIds("1");
        order.setPaymentType(orderDTO.getPaymentType());
        order.setPostFee(50L);
        order.setUserId(userInfo.getId());
        order.setInvoiceType(0);
        order.setSourceType(2);
        order.setStatus(OrderStatusEnum.INIT.value());
        //3.保存订单的物流信息表数据
        orderMapper.insert(order);
        //2.保存订单明细表数据
        if (CollectionUtils.isNotEmpty(skuList)){
            skuList.forEach(sku->{
                OrderDetail orderDetail = new OrderDetail();
                orderDetail.setId(idWorker.nextId());
                orderDetail.setOrderId(order.getOrderId());
                orderDetail.setSkuId(sku.getId());
                orderDetail.setNum(skuMap.get(sku.getId()));
                orderDetail.setTitle(sku.getTitle());
                orderDetail.setPrice(sku.getPrice());
                orderDetail.setOwnSpec(sku.getOwnSpec());
                orderDetail.setImage(sku.getImages());
                orderDetailMapper.insert(orderDetail);
            });
        }
        //3.保存订单的物流信息表数据
        //1）根据地址ID查询收货地址信息
     AddressDTO addressId = userClient.findAddressId(userInfo.getId(), orderDTO.getAddressId());
        //2）把AddressDTO数据拷贝到物流对象中
        OrderLogistics orderLogistics = BeanHelper.copyProperties(addressId, OrderLogistics.class);
        //3）补充信息
        orderLogistics.setOrderId(order.getOrderId());//订单ID
        orderLogistics.setLogisticsNumber("SF0001");//物流单号
        orderLogistics.setLogisticsCompany("顺丰物流");//物流公
        orderLogisticsMapper.insert(orderLogistics);
         itemClient.minusStock(skuMap);
        return  order.getOrderId();
    }


    public OrderVO findOrdeById(Long id) {
        //1.查询Order
        Order order = orderMapper.selectById(id);
        OrderVO orederVo = BeanHelper.copyProperties(order, OrderVO.class);
        //2.查询物流信息，并封装
        OrderLogistics orderLogistics = orderLogisticsMapper.selectById(id);
        orederVo.setLogistics(orderLogistics);
        //3.查询订单明细
        OrderDetail orderDetail = new OrderDetail();
        orderDetail.setId(id);
        QueryWrapper<OrderDetail> query = Wrappers.query(orderDetail);
        List<OrderDetail> orderDetails = orderDetailMapper.selectList(query);
        orederVo.setDetailList(orderDetails);
        return  orederVo;
    }

    public String getPayUrl(Long id) {
       String payUrl= redisTemplate.opsForValue().get(LyConstants.PAY_URL_PRE+id);
       if (StringUtils.isEmpty(payUrl)){
           Order order = orderMapper.selectById(id);
           Long actualFee = order.getActualFee();
           payUrl = payHelper.getPayUrl(id, actualFee);
           redisTemplate.opsForValue().set(LyConstants.PAY_URL_PRE,payUrl,2, TimeUnit.HOURS);
       }
       return payUrl;
    }

    public void wxNotify(Map<String, String> paraMap) {
        //1.接收参数
        Long orderId = Long.valueOf(paraMap.get("out_trade_no"));
        Long  totalFee=Long.valueOf(paraMap.get("total_fee"));
        //订单数据的校验
        Order order = orderMapper.selectById(orderId);
        if (order==null){
            log.error("支付回调 非法定单");
            throw new LyException(500,"非法订单");
        }
        if (order.getActualFee()!=totalFee){
            log.error("支付回调 订单金额不一致");
            throw new LyException(500,"订单实付金额不一致");
        }

        //更新订单信息
        try {
            order.setStatus(OrderStatusEnum.PAY_UP.value());
            order.setPayTime(new Date());
            orderMapper.updateById(order);
            log.info("支付回调 订单信息更新成功");
        } catch (Exception e) {
            e.printStackTrace();
            log.error("支付回调 订单信息更新失败");
            throw new LyException(500,"订单信息更新失败");
        }
    }

    public Integer  checkState(Long id) {
        Order order = orderMapper.selectById(id);
        return order.getStatus();
    }
}
